﻿/// <summary>
/// FileName: Token.cs
/// Author: Jiang Xiaolong
/// Created Time: 2015.05.12
/// Version: 1.0
/// Company: Sunnytech
/// Function: 基本分词结构，继承PositionLocate接口，便于错误定位；
///
/// Changed By:
/// Modification Time:
/// Discription:
/// </summary>
using System;
using Expression.api;

namespace Expression.impl
{
	public class Token : PositionLocate
	{
		/// <summary>
		/// 当前支持识别的类型；
		/// </summary>
		public enum TokenType
		{
			ID, SPECIAL_ID, KEYWORD, STRING, INTEGER, OPERATOR, BOOL, FLOAT, DOUBLE, EOI
		}

		public TokenType type;

		private string _source = "";
		private string _contents = "";
		private string _trigger = "";

		private int _line = 0;
		private int _pos = 0;

		public Token()
		{

		}

		/// <summary>
		/// 实例化一个分词，类似一个工厂；
		/// </summary>
		/// <param name="type">分词类型；</param>
		/// <param name="pos">分词位置信息；</param>
		/// <returns>新创建的分词；</returns>
		public static Token Create(TokenType type, PositionLocate pos)
		{
			Token result = new Token();
			result.type = type;
			result._line = pos.GetLine();
			result._pos = pos.GetPos();

			return result;
		}

		/// <summary>
		/// 创建并且实例化当前分词；
		/// </summary>
		/// <param name="type">当前分词类型；</param>
		/// <param name="ch">当前字符；</param>
		/// <returns>当前分词；</returns>
		public static Token CreateAndFill(TokenType type, ExpChar ch)
		{
			Token result = new Token();
			result.type = type;
			result._line = ch.GetLine();
			result._pos = ch.GetPos();
			result._contents = ch.GetStringValue();
			result._trigger = ch.GetStringValue();
			result._source = ch.ToString();
			return result;
		}

		/// <summary>
		/// 设置控制字符；
		/// </summary>
		/// <param name="ch">控制字符‘</param>
		/// <returns>当前分词；</returns>
		public Token AddToTrigger(ExpChar ch)
		{
			_trigger += ch.GetValue();
			_source += ch.GetValue();
			return this;
		}

		/// <summary>
		/// 加入到Source变量，对于“Test:”或者“$Test”，Contents中只有“Test”，Source中则完全表示；
		/// </summary>
		/// <param name="ch">当前读取字符；</param>
		/// <returns>当前分词；</returns>
		public Token AddToSource(ExpChar ch)
		{
			_source += ch.GetValue();
			return this;
		}

		/// <summary>
		/// 添加计算数；
		/// </summary>
		/// <param name="ch">自定义单个字符；</param>
		/// <returns>当前分词；</returns>
		public Token AddToContent(ExpChar ch)
		{
			return AddToContent(ch.GetValue());
		}

		/// <summary>
		/// 添加计算数；
		/// </summary>
		/// <param name="ch">单个字符；</param>
		/// <returns>当前分词；</returns>
		public Token AddToContent(char ch)
		{
			_contents += ch;
			_source += ch;
			return this;
		}

		/// <summary>
		/// 一些特殊字符不添加到source；
		/// </summary>
		/// <param name="ch">特殊字符；</param>
		/// <returns>当前分词；</returns>
		public Token SilentAddToContent(char ch)
		{
			_contents += ch;
			return this;
		}

		/// <summary>
		/// 当前分词控制字符；
		/// </summary>
		/// <returns>当前分词控制字符；</returns>
		public string GetTrigger()
		{
			return _trigger;
		}

		/// <summary>
		/// 当前分词类型；
		/// </summary>
		/// <returns>当前分词类型；</returns>
		public TokenType GetTokenType()
		{
			return type;
		}

		/// <summary>
		/// 获取当前分词内容；
		/// </summary>
		/// <returns>获取当前分词内容；</returns>
		public string GetContents()
		{
			return _contents;
		}

		/// <summary>
		/// 获取当前分词原始内容；
		/// </summary>
		/// <returns>获取当前分词原始内容；</returns>
		public string GetSource()
		{
			return _source;
		}

		/// <summary>
		/// 获取当前分词行号；
		/// </summary>
		/// <returns>行号；</returns>
		public int GetLine()
		{
			return _line;
		}

		/// <summary>
		/// 获取当前分词位置信息；
		/// </summary>
		/// <returns>位置信息；</returns>
		public int GetPos()
		{
			return _pos;
		}

		/// <summary>
		/// 设置当前分词类型；
		/// </summary>
		/// <param name="new_type">新分词类型；</param>
		public void SetTokenType(TokenType new_type)
		{
			this.type = new_type;
		}

		/// <summary>
		/// 设置控制器；
		/// </summary>
		/// <param name="trigger">当前控制器；</param>
		public void SetTrigger(string trigger)
		{
			this._trigger = trigger;
		}

		/// <summary>
		/// 设置当前分词内容；
		/// </summary>
		/// <param name="content">内容字符串；</param>
		public void SetContent(string content)
		{
			this._contents = content;
		}

		/// <summary>
		/// 设置当前分词与原始内容；
		/// </summary>
		/// <param name="source">原始内容字符串；</param>
		public void SetSource(string source)
		{
			this._source = source;
		}


		/// <summary>
		/// 是否为行尾；
		/// </summary>
		/// <returns>是否为行尾；</returns>
		public bool IsEnd()
		{
			return type == TokenType.EOI;
		}

		/// <summary>
		/// 是否满足该条件；
		/// </summary>
		/// <param name="type"></param>
		/// <param name="trigger"></param>
		/// <returns></returns>
		public bool Matches(TokenType type, string trigger)
		{
			if (!Is(type))
			{
				return false;
			}
			if (trigger == "")
			{
				return false;
			}
			return GetTrigger() == trigger;
		}

		/// <summary>
		/// 是否有该Trigger
		/// </summary>
		/// <param name="triggers"></param>
		/// <returns></returns>
		public bool WasTriggeredBy(params string[] triggers)
		{
			if (triggers.Length == 0)
			{
				return false;
			}
			foreach (string aTrigger in triggers)
			{
				if (aTrigger != null && aTrigger == GetTrigger())
				{
					return true;
				}
			}

			return false;
		}

		/// <summary>
		/// 是否有内容
		/// </summary>
		/// <param name="content"></param>
		/// <returns></returns>
		public bool HasContent(string content)
		{
			if (content == "")
			{
				return false;
			}
			return content.Equals(GetContents(), StringComparison.CurrentCultureIgnoreCase);
		}

		/// <summary>
		/// 判断类型；
		/// </summary>
		/// <param name="type"></param>
		/// <returns></returns>
		public bool Is(TokenType type)
		{
			return this.type == type;
		}

		/// <summary>
		/// 判断是否为运算符；
		/// </summary>
		/// <param name="symbols">当前输入运算符；</param>
		/// <returns>是否为运算符；</returns>
		public bool IsOperator(params string[] symbols)
		{
			if (symbols.Length == 0)
			{
				return Is(TokenType.OPERATOR);
			}
			foreach (string symbol in symbols)
			{
				if (Matches(TokenType.OPERATOR, symbol))
				{
					return true;
				}
			}
			return false;
		}

		/// <summary>
		/// 当前是否为前括号；
		/// </summary>
		/// <returns>当前是否为前括号；</returns>
		public bool IsStartBracket()
		{
			if (Is(TokenType.OPERATOR))
			{
				if (_trigger == "(" || _trigger == "（" || _trigger == "[" || _trigger == "【" || _trigger == "{")
				{
					return true;
				}
				else
				{
					return false;
				}
			}
			else
			{
				return false;
			}
		}

		/// <summary>
		/// 当前是否为后括号；
		/// </summary>
		/// <returns>当前是否为后括号；</returns>
		public bool IsEndBracket()
		{
			if (Is(TokenType.OPERATOR))
			{
				if (_trigger == ")" || _trigger == "）" || _trigger == "]" || _trigger == "】" || _trigger == "}")
				{
					return true;
				}
				else
				{
					return false;
				}
			}
			else
			{
				return false;
			}
		}

		/// <summary>
		/// 判断是否为关键字；
		/// </summary>
		/// <param name="keywords"></param>
		/// <returns></returns>
		public bool IsKeyword(params string[] keywords)
		{
			if (keywords.Length == 0)
			{
				return Is(TokenType.KEYWORD);
			}
			foreach (string keyword in keywords)
			{
				if (Matches(TokenType.KEYWORD, keyword))
				{
					return true;
				}
			}
			return false;
		}

		/// <summary>
		/// 判断是否为一个标识符；
		/// </summary>
		/// <param name="values"></param>
		/// <returns></returns>
		public bool IsIdentifier(params string[] values)
		{
			if (values.Length == 0)
			{
				return Is(TokenType.ID);
			}
			foreach (String value in values)
			{
				if (Matches(TokenType.ID, value))
				{
					return true;
				}
			}
			return false;
		}

		/// <summary>
		/// 是否为特殊ID；
		/// </summary>
		/// <param name="triggers"></param>
		/// <returns></returns>
		public bool IsSpecialIdentifier(params string[] triggers)
		{
			if (triggers.Length == 0)
			{
				return Is(TokenType.SPECIAL_ID);
			}
			foreach (string trigger in triggers)
			{
				if (Matches(TokenType.SPECIAL_ID, trigger))
				{
					return true;
				}
			}
			return false;
		}

		/// <summary>
		/// 特殊ID是否有内容；
		/// </summary>
		/// <param name="trigger"></param>
		/// <param name="contents"></param>
		/// <returns></returns>
		public bool IsSpecialIdentifierWithContent(string trigger, params string[] contents)
		{
			if (!Matches(TokenType.SPECIAL_ID, trigger))
			{
				return false;
			}
			if (contents.Length == 0)
			{
				return true;
			}
			foreach (string content in contents)
			{
				if (content != null && content.Equals(GetContents()))
				{
					return true;
				}
			}
			return false;
		}

		/// <summary>
		/// 是否为Int；
		/// </summary>
		/// <returns></returns>
		public bool IsInteger()
		{
			return Is(TokenType.INTEGER);
		}

		/// <summary>
		/// 是否为bool；
		/// </summary>
		/// <returns></returns>
		public bool IsBool()
		{
			return Is(TokenType.BOOL);
		}

		/// <summary>
		/// 是否为Float；
		/// </summary>
		/// <returns></returns>
		public bool IsFloat()
		{
			return Is(TokenType.FLOAT);
		}

		/// <summary>
		/// 是否为double；
		/// </summary>
		/// <returns></returns>
		public bool IsDouble()
		{
			return Is(TokenType.DOUBLE);
		}

		/// <summary>
		/// 是否为数字类型；
		/// </summary>
		/// <returns></returns>
		public bool IsNumber()
		{
			return IsInteger() || IsFloat() || IsDouble();
		}

		/// <summary>
		/// 是否为常量操作数；
		/// </summary>
		/// <returns></returns>
		public bool IsConstant()
		{
			return IsInteger() || IsFloat() || IsDouble() || IsString() || IsBool();
		}

		/// <summary>
		/// 是否为字符串常量；
		/// </summary>
		/// <returns></returns>
		public bool IsString()
		{
			return Is(TokenType.STRING);
		}

		public override string ToString()
		{
			return GetTokenType().ToString() + ":" + GetContents() + " (" + _line + ":" + _pos + ")" + " Trigger: " + GetTrigger();
		}
	}

}
